package cn.qingyun.gis.modules.express.controller;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import cn.qingyun.gis.cache.common.facade.CacheFacade;
import cn.qingyun.gis.cache.constant.CacheConstant;
import cn.qingyun.gis.common.Result;
import cn.qingyun.gis.exception.CommonException;
import cn.qingyun.gis.modules.express.request.AppSsoLoginRequest;
import cn.qingyun.gis.modules.express.response.AppSsoLoginResponse;
import cn.qingyun.gis.modules.express.service.IExpressProofreadService;
import cn.qingyun.gis.modules.express.util.EncryptionUtil;
import cn.qingyun.gis.modules.express.util.URLUtil;
import cn.qingyun.gis.modules.express.util.UbopSignUtil;
import cn.qingyun.gis.modules.init.system.constant.CommonConstant;
import cn.qingyun.gis.modules.init.system.entity.SysUser;
import cn.qingyun.gis.modules.init.system.service.IBaseCommonService;
import cn.qingyun.gis.modules.init.system.service.ISysUserService;
import cn.qingyun.gis.modules.init.system.vo.LoginUser;
import cn.qingyun.gis.modules.init.utils.JwtUtil;
import cn.qingyun.gis.modules.init.utils.MD5Util;
import com.google.common.collect.Maps;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;

@RestController
@RequestMapping("/app/sso")
@Slf4j
public class AppSsoLoginController {
    @Resource
    private ISysUserService iSysUserService;
    @Resource
    private IBaseCommonService iBaseCommonService;
    @Resource
    private IExpressProofreadService iExpressProofreadService;

    @Value("${qingyun.sso.valid.enabled:false}")
    private Boolean ssoValid;

    @Value("${qingyun.sso.aes-key:82f2672863c924f130879734b4d9431c}")
    private String ssoAesKey; //

    @Value("${qingyun.sso.aes-vi:f205652576f98802}")
    private String ssoAesVi; //

    @Value("${spring.profiles.active}")
    private String env;

    @SneakyThrows
    @PostMapping("/login")
    public Result<?> login(@RequestBody AppSsoLoginRequest request, HttpServletRequest httpServletRequest) {
        log.debug("登录接口入参 {}", JSONUtil.toJsonStr(request));
        TreeMap<String, String> decryptedMap = Maps.newTreeMap();
//        if(StrUtil.isEmpty(request.getUrl())){
//            throw new CommonException("跳转url为空");
//        }
//        String decodeUrl = URLDecoder.decode(URLDecoder.decode(request.getUrl(), StandardCharsets.UTF_8.name()), StandardCharsets.UTF_8.name());
        if (Boolean.TRUE.equals(ssoValid)) {
            // 验证手机端登录 暂时注掉
            //SsoTool.validRequestFromMobile(httpServletRequest);
            // 参数解析
            TreeMap<String, String> encryptedMap = URLUtil.parsingURLToUri(request.getUrl());
            log.debug("解析参数列表parsingURLToUri(密文) {}", JSONUtil.toJsonStr(encryptedMap));
            log.debug("配置密钥：{}，配置偏移量：{}", ssoAesKey, ssoAesVi);
            for (Map.Entry<String, String> entry : encryptedMap.entrySet()) {
                String k = entry.getKey();
                String v = entry.getValue();
                if ("timestamp".equals(k) || "ubopSign".equals(k)) {
                    decryptedMap.put(k, v);
                } else {
                    try {
                        decryptedMap.put(k, EncryptionUtil.AESDecrypt(v, ssoAesKey, ssoAesVi));
                    } catch (Exception e) {
                        decryptedMap.put(k, URLDecoder.decode(URLDecoder.decode(v)));
                    }
                }
            }
            //只有生产环境才校验签名
            if (env.equals("prod")){
                // 验证签名
                boolean urlValid = UbopSignUtil.checkGetUbopSign(URLDecoder.decode(URLDecoder.decode(request.getUrl())), ssoAesKey);
                if (!urlValid) {
                    throw new CommonException("非法的请求，接口签名校验失败");
                }
            }
        } else {
            decryptedMap = URLUtil.parsingURLToUri(request.getUrl());
        }
        log.debug("解析参数列表parsingURLToUri(明文) {}", JSONUtil.toJsonStr(decryptedMap));
        if (decryptedMap.isEmpty() || StringUtils.isEmpty(decryptedMap.get("telNum"))){
            throw new CommonException("未获取到工号请退出重试！");
        }
        // 对中文进行url解码
        try {
            if (ObjectUtil.isNotEmpty(decryptedMap.get("username"))) {
                String username = URLDecoder.decode(decryptedMap.get("username"), StandardCharsets.UTF_8.name());
                String decodeUserName = URLDecoder.decode(username, StandardCharsets.UTF_8.name());
                decryptedMap.put("username", ObjectUtil.isNotEmpty(decodeUserName) ? decodeUserName : decryptedMap.get("username"));
                log.debug("url中文参数解析列表(明文) {}", JSONUtil.toJsonStr(decryptedMap));
            }
        } catch (Exception e) {
            log.error("解析username报错", e);
        }
        // 保证自动同步系统用户， 前提是有guest 权限
        SysUser sysUser = iSysUserService.ensureUserIsValidWithGuestAuth(decryptedMap.get("telNum"), decryptedMap.get("crmAccount"), decryptedMap.get("telNum"));
        log.debug("解析已同步guest权限用户参数列表{}", JSONUtil.toJsonStr(sysUser));
        String token = JwtUtil.sign(sysUser.getUsername(), MD5Util.MD5Encode(CharSequenceUtil.emptyIfNull(sysUser.getPassword()), StandardCharsets.UTF_8.name()));
        CacheFacade.set(CommonConstant.PREFIX_USER_TOKEN + token, token, JwtUtil.EXPIRE_TIME / 1000);
        CacheFacade.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);

        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(sysUser, loginUser);
        loginUser.setPassword(SecureUtil.md5(sysUser.getPassword()));
        CacheFacade.set(CacheConstant.SYS_USERS_CACHE_JWT + ":" + token, loginUser, JwtUtil.EXPIRE_TIME / 1000);
        CacheFacade.expire(CacheConstant.SYS_USERS_CACHE_JWT + ":" + token, JwtUtil.EXPIRE_TIME / 1000);
        iBaseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功！", CommonConstant.LOG_TYPE_1, null, loginUser);
        //return Result.okData(SsoLoginResponse.builder().token(token).params(decryptedMap).build());
        // 判定网格区域权限
        TreeMap<String, String> permissionMap = new TreeMap<>();
        if (ssoValid.equals(Boolean.TRUE)||"test".equals(env)) {
            permissionMap = iExpressProofreadService.areaPermissionByNum(decryptedMap);
        } else if (ssoValid.equals(Boolean.FALSE)) { // 本地 测试环境 不走 权限接口
            permissionMap.put("gridType", "province"); //传入权限区域类型 province un_province
            permissionMap.put("gridId", "531.0003.2111");
            permissionMap.put("telNum", "0000006t");
            permissionMap.put("username", "测试姓名");
            permissionMap.put("channelCode", "");
            permissionMap.put("userId", "test123");
        }

        log.debug("解析权限参数列表(明文) {}", JSONUtil.toJsonStr(permissionMap));
        log.debug("存放在redis中的token为：" + CacheFacade.get(CommonConstant.PREFIX_USER_TOKEN + token));
        return Result.okData(AppSsoLoginResponse.builder().token(token).params(permissionMap).build());
    }

    @GetMapping("/ys/login")
    public Result<?> ysLogin(String telNum) {
        log.debug("接口入参 {}", telNum);
        // 判定网格区域权限
        TreeMap<String, String> permissionMap = iExpressProofreadService.areaYsPermissionByNum(telNum);
        log.debug("解析权限参数列表(明文) {}", JSONUtil.toJsonStr(permissionMap));
        return Result.okData(permissionMap);
    }
}
